/*
 Created by lustre on 2023/9/30.
 version 0.1.0.0
*/

#ifdef LIGHT_TCP_H
// 不能与LightClient同时使用，需要解决一些冲突
#warning "MAY CONFLICT WITH LIGHT TCP"
#endif
/**
 * arduino ide并不支持颜色 使用platformio时 将monitor_filters 里面加一个 direct
 * */
#if CONFIG_ARDUHAL_LOG_COLORS

#define ERROR_PRE "\033[31m"
#define INFO_PRE "\033[32m"
#define END_LOG_LINE "\033[0m"
#else
#define ERROR_PRE ""
#define INFO_PRE ""
#define END_LOG_LINE ""
#endif
#define serial_info(x) Serial.println(INFO_PRE \
x \
END_LOG_LINE)

#define serial_infof(x, ...) Serial.printf(INFO_PRE \
x \
END_LOG_LINE,##__VA_ARGS__)

#define serial_error(x) Serial.println(ERROR_PRE \
x \
END_LOG_LINE)

#define serial_errorf(x, ...) Serial.printf(ERROR_PRE \
x \
END_LOG_LINE, ##__VA_ARGS__)

#ifndef LIGHT_UDP_CLIENT_H
#define LIGHT_UDP_CLIENT_H

#define LIGHT_UDP_VERSION "0.1.0.0"

#include "UdpClient.hpp"

#ifdef ESP32

#include <MD5Builder.h>
#include <WiFi.h>

#elif defined(ESP8266)

#endif
// 引入当前头文件需要先引入Arduino.h

//上位机为热点时 接收通知的端口
#define AS_GATE_WAY_PORT 8001
#define MTU_SIZE 1300

#define MSG_OK 0
#define MSG_FAILED (-1)
const uint8_t MAC_LEN = 6;


typedef struct {
    int cmdIdVal;
    int opCode;
} MsgHeader;

typedef struct {
    // wifi 的ssid和密码
    char const *ssid;
    char const *passphrase;
    // 服务端地址与端口
    char const *host;
    uint16_t serverPort;
    // 设备用户名密码
    char const *userName;
    const char *passwd;
    // 设备属性数，和属性
    uint16_t attrCount;
    const char *devAttr;
} ConnectInfo;

class LightUdpClient {

private:
    LightUDP client;
    uint8_t rxBuffer[MTU_SIZE]{};
    int messageLength{0};
    int readIndex{0};
    char resultBuffer[MTU_SIZE]{};
    uint8_t mac[MAC_LEN]{0};
    uint8_t keepRequest[12] = {
            4,                  // header len
            'k', 'e', 'e', 'p', // header keep
            6,                  // snLen
            0, 0, 0, 0, 0, 0}; // sn 这里是mac

    IPAddress getServerHost();

    inline int recvByTimes(uint8_t times, uint8_t delayMills, size_t length);

    inline int readUntil(uint8_t terminator);

    inline bool checkKey(int length, const char *keyName);

    inline void sendAction(uint8_t **action, const size_t *sizeTab, size_t subCount);

    inline void dropErrorInfo(const uint8_t *info, size_t len);

    static void connectWifi(const char *ssid, const char *passphrase);

    bool login(const char *userName, const char *passwd);

    void helloServer(const uint16_t attrCount, const char *devAttr);

    static void reStartApp(const char *failedCause);

    unsigned long lastHeartbeatTime{0};

public:

    int readMsgHeader(MsgHeader *msgHeader);

    int readInt(uint8_t terminator);

    String readStringUntil(uint8_t terminator);

    IPAddress connectServer(ConnectInfo *connectInfo);

    /**
     * 过nat路由连接服务器时，需要定时发包给服务器，用于刷新nat，
     * 防止服务器无法将包发送到局域网。
     * */
    void startHeartbeat();

};

#endif //LIGHT_UDP_CLIENT_H
